package org.apache.rocketmq.namesrv.test;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BiConsumer;
import java.util.function.Function;


/**
 * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
 * @author：陈清风扬，个人微信号：chenqingfengyangjj。
 * @方法描述：自定义的CompletableFuture类，这个类是JDK1.8中的CompletableFuture的简化版，用于学习CompletableFuture的原理。目前这个类的内容大约是源码的三分之一。
 */
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {

 
    //同步模式,表示在当前线程中直接执行完成动作
    static final int SYNC   =  0;
    //异步模式,表示在异步线程中执行完成动作
    static final int ASYNC  =  1;
    //嵌套模式,表示在处理其他完成动作过程中触发的完成动作
    static final int NESTED = -1;

    //在CompletableFuture中，所有要执行的任务都会被包装成Completion对象，然后放入这个栈中
    //这个栈是一个单向链表，每个Completion对象都有一个next指针，指向下一个Completion对象
    //当所有任务要执行的时候，就会根据这个栈的结构，依次执行栈里面的每个任务
    volatile Completion stack;
    
    //用于标识任务执行结果为null，如果某个任务执行结果为null或者没有结果，那么这个任务的执行结果就是NIL
    static final AltResult NIL = new AltResult(null);

    //当前CompletableFuture对象要执行的任务的执行结果
    volatile Object result;

    //以下是几个原子操作成员变量
    //这个成员变量主要用来原子操作CompletableFuture类的result成员变量
    private static final VarHandle RESULT;
    //这个成员变量主要用来原子操作CompletableFuture类的stack成员变量
    private static final VarHandle STACK;
    //这个成员变量主要用来原子操作Completion类的next成员变量
    private static final VarHandle NEXT;

    //在这个静态代码块中给上面三个成员变量赋值，操作都很简单，我就不添加注释了
    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            RESULT = l.findVarHandle(CompletableFuture.class, "result", Object.class);
            STACK = l.findVarHandle(CompletableFuture.class, "stack", Completion.class);

            NEXT = l.findVarHandle(Completion.class, "next", Completion.class);
        } catch(ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
        //减少在首次调用LockSupport.park时发生罕见灾难性类加载的风险
        //这是为了解决JDK-8074773 bug,通过提前确保LockSupport类被加载
        //预先触发LockSupport类的加载,避免在关键时刻触发类加载带来的延迟
        Class<?> ensureLoaded = LockSupport.class;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：创建一个新的CompletableFuture对象的方法
     */
    public <U> CompletableFuture<U> newIncompleteFuture() {
        return new CompletableFuture<U>();
    }



    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：取消任务的方法
     */
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        //把创建的这个AltResult结果对象赋值给CompletableFuture的result成员变量
        boolean cancelled = (result == null) &&
                internalComplete(new AltResult(new CancellationException()));
        //这个方法会递归的处理当前阶段的下游任务栈，直到所有任务都被处理完
        postComplete();
        //返回任务是否被成功取消的结果
        return cancelled || isCancelled();
    }

    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：原子更新当前阶段的任务结果为result的方法
     */
    final boolean internalComplete(Object result) {
        return RESULT.compareAndSet(this, null, result);
    }

    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：判断当前阶段的任务是否已取消
     */
    @Override
    public boolean isCancelled() {
        return (result instanceof AltResult) && (((AltResult) result).ex instanceof CancellationException);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：判断当前阶段的任务是否已完成
     */
    @Override
    public boolean isDone() {
        return this.result != null;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：获取任务结果的方法，如果任务未完成，需要阻塞等待一段时间
     */
    @SuppressWarnings("unchecked")
    public T join() {
        Object result = this.result;
        if(result == null) {
            //获取任务结果的方法，如果任务未完成，需要阻塞等待一段时间
            //方法参数false表示遇到线程中断时不会退出
            result = waitingGet(false);
        }//处理并返回任务执行结果
        return (T) reportJoin(result);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：获取任务结果的方法，如果任务未完成，需要阻塞等待一段时间
     */
    @Override
    @SuppressWarnings("unchecked")
    public T get() throws InterruptedException, ExecutionException {
        Object r;
        if ((r = result) == null)
            //获取任务结果的方法，如果任务未完成，需要阻塞等待一段时间
            //方法参数true表示遇到线程中断时会停止等待
            r = waitingGet(true);
        //处理并返回任务执行结果
        return (T) reportGet(r);
    }

    

    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：限时获取任务执行结果的方法
     */
    @Override
    @SuppressWarnings("unchecked")
    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        //将等待超时时间转换为纳秒
        long nanos = unit.toNanos(timeout);
        Object r;
        if ((r = result) == null)
            //如果任务还没有结果，就限时等待获取结果
            r = timedGet(nanos);
        //处理并返回任务执行结果
        return (T) reportGet(r);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：立即返回响应结果的方法，如果没有响应结果，则返回默认值
     */
    @SuppressWarnings("unchecked")
    public T getNow(T valueIfAbsent) {
        Object r;
        return ((r = result) == null) ? valueIfAbsent : (T) reportJoin(r);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：对响应结果进行处理的方法
     */
    private static Object reportGet(Object r) throws InterruptedException, ExecutionException {
        //如果结果为null，直接抛出线程中断异常
        if (r == null)
            throw new InterruptedException();
        if (r instanceof AltResult) {
            Throwable x, cause;
            if ((x = ((AltResult)r).ex) == null)
                return null;
            if (x instanceof CancellationException)
                throw (CancellationException)x;
            if ((x instanceof CompletionException) &&
                    (cause = x.getCause()) != null)
                x = cause;
            throw new ExecutionException(x);
        }
        return r;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：处理响应结果的方法
     */
    private static Object reportJoin(Object r) {
        if (r instanceof AltResult) {
            Throwable x;
            if ((x = ((AltResult)r).ex) == null)
                return null;
            if (x instanceof CancellationException)
                throw (CancellationException)x;
            if (x instanceof CompletionException)
                throw (CompletionException)x;
            throw new CompletionException(x);
        }
        return r;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：等待获取任务执行结果的方法，如果方法参数为true，那么遇到线程中断时会退出等待的操作，如果方法参数为false，那么遇到线程中断时不会退出等待的操作
     */
    private Object waitingGet(boolean interruptible) {
        //如果等待的操作可中断并且执行当前方法的线程已被中断
        //直接返回null即可
        if (interruptible && Thread.interrupted())
            return null;
        //定义一个Signaller对象，这个对象是用来管理阻塞调用当前方法的线程的
        //假如有一个线程调用了get方法获取任务执行结果，那么就会在get方法中调用到当前方法
        //这个Signaller对象就是用来管理这个线程是否需要阻塞的，任务没有执行完毕的情况下，这个线程就需要阻塞
        //Signaller内部有一个thread成员变量，用来记录调用当前方法的线程
        Signaller q = null;
        //定义一个标志，表示刚才创建的signaller对象是否已经加入到下游任务栈中了
        boolean queued = false;
        //任务的执行结果
        Object r;
        //判断任务是否执行完毕了
        while ((r = result) == null) {
            //如果任务没有执行完毕，这时候就意味着调用当前方法的线程需要阻塞一会儿
            if (q == null) {
                //所以会再判断signaller对象是否还没创建，如果没有创建则直接创建
                //这个signaller是当前CompletableFuture类的一个内部类
                q = new Signaller(interruptible, 0L, 0L);
            }
            //判断Signaller是否已经加入到下游任务栈中了
            //如果没有加入到下游任务栈中，那么就加入到下游任务栈中
            //我简单解释一下这里的逻辑，实际上是这样的，如果程序执行到这里，肯定就意味着任务没有执行完毕
            //没有返回结果，这个时候线程就会阻塞，而把Signaller加入到当前正在执行的任务的下游任务栈中，就是为了让这个任务执行完毕后，能执行任务栈后面的任务
            //也就是这个Signaller任务，在这个Signaller任务执行的时候，它的tryFire方法会被调用，会唤醒阻塞的线程，也就是唤醒调用当前方法的线程
            //然后线程就可以继续执行下去了
            else if (!queued)
                //如果没有加入到下游任务栈中，那么就加入到下游任务栈中
                queued = tryPushStack(q);
                //每次循环都要判断线程是否被中断了，并且是否支持线程中断就退出当前等待的操作。注意，本来线程应该在ForkJoinPool.managedBlock(signaller);这行代码阻塞的
                //但是可能任务执行完毕，线程被唤醒了，也可能是线程直接被中断了，所以程序可以执行到这里，
                //如果线程被中断了，并且interruptible为true，那就可以不用再等待任务执行完毕，直接打断循环，退出当前方法即可
                //如果interruptible为false，就意味着不能退出当前方法，还需要继续等待任务执行完毕，不会进入下面的分支
            else if (interruptible && q.interrupted) {
                //程序执行到这里意味着线程被中断了，那就不必再等待任务执行完毕了
                //直接退出当前方法即可，既然不必再等待任务执行完毕，也就意味着当前线程没必要再阻塞了
                //那么Signaller对象也就没必要再管理当前线程了，也没必要再加入到下游任务栈中了
                //所以这里把Signaller对象的thread成员变量设置为null，表示不再管理当前线程
                q.thread = null;
                //把Signaller从下游任务栈中移除
                cleanStack();
                //直接返回null即可
                return null;
            }
            //如果程序执行到下面的分支，就意味着线程并没有中断，需要阻塞等待任务执行完毕
            else {
                try {
                    //接下来就是阻塞当前线程的操作，因为Signaller类实现了ForkJoinPool.ManagedBlocker接口
                    //所以可以被ForkJoinPool来管理，在ForkJoinPool中，会调用Signaller的block方法阻塞Signaller管理的线程
                    ForkJoinPool.managedBlock(q);
                } catch (InterruptedException ie) {
                    //这里的逻辑就比较重要了，首先大家应该知道中断线程的操作，也就是这个Thread.interrupt()这个方法
                    //只要线程一调用这个方法，虽然线程不会停止工作，但是给自己施加一个中断标记，如果这个线程正处于阻塞中
                    //这个时候就会抛出一个InterruptedException异常，在当前的catch中，捕获到的就是线程中断异常
                    //只要捕获到了这个异常，就意味着线程中断了，这个时候就可以更新Signaller的interrupted成员变量为true
                    //表示它管理的线程被中断了，注意，抛出这个异常的时候，线程的中断标志就被重置了
                    q.interrupted = true;
                }
            }
        }
        //执行到这里意味着跳出上面的循环了，可能是任务执行完毕了，或者线程被中断了
        //清理Signaller资源即可
        if (q != null) {
            q.thread = null;
            //如果线程被中断了，就恢复线程的中断状态
            if (q.interrupted)
                Thread.currentThread().interrupt();
        }
        //执行后续操作，传播完成状态给下游的CompletableFuture
        postComplete();
        //返回执行结果
        return r;
    }



    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：限时等待获取任务执行结果的方法，这个方法的核心逻辑和上面的waitingGet()方法基本一样，只是多了一个超时时间的判断
     */
    private Object timedGet(long nanos) throws TimeoutException {
        //计算线程等待的截止时间，其实就是当前纳秒时间加上等待的纳秒时间
        long d = System.nanoTime() + nanos;
        //对截止时间做一个判断，如果截止时间为0，那么就设置为1，如果是0的话，就会一直等待，表示无截至时间
        long deadline = (d == 0L) ? 1L : d;
        //定义一个标记，表示线程是否被中断
        boolean interrupted = false;
        //定义一个标记，表示Signaller是否已经加入到下游任务栈中了
        boolean queued = false;
        //定义一个Signaller对象，用来管理阻塞调用当前方法的线程
        Signaller q = null;
        //声明任务执行结果变量
        Object r = null;
        //进入死循环，直到线程被中断，或者等待超时，或者任务执行完毕
        for (;;) {
            //每一次循环开始的时候检查线程是否被中断，如果被中断，就跳出循环
            if (interrupted || (interrupted = Thread.interrupted()))
                break;
            //如果任务执行完毕，就跳出循环
            else if ((r = result) != null)
                break;
            //如果等待已经超时，跳出循环即可
            else if (nanos <= 0L)
                break;
            //判断Signaller是否已经创建了，没有创建则创建一个Signaller对象
            else if (q == null) {
                //在这里创建了Signaller对象，并且设置了该对象管理的线程等待时间和等待的截止时间
                q = new Signaller(true, nanos, deadline);
            }
            //如果新创建的Signaller对象没有加入下游任务栈中，就加入进去
            else if (!queued)
                queued = tryPushStack(q);
            //程序执行到这个分支就意味着线程没有被中断，任务也没有执行完毕，还没有结果，这时候就意味着调用了当前方法的线程需要阻塞等待一会了
            else {
                try {
                    //接下来就是阻塞当前线程的操作，因为Signaller类实现了ForkJoinPool.ManagedBlocker接口
                    //所以可以被ForkJoinPool来管理，在ForkJoinPool中，会调用Signaller的block方法阻塞Signaller管理的线程
                    ForkJoinPool.managedBlock(q);
                    //得到线程是否被中断了的标志
                    interrupted = q.interrupted;
                    //得到剩余的等待时间，其实执行到这里肯定就意味着已经等待了指定的时间了
                    //这里得到的值就是0，表示已经等待了指定的时间了
                    nanos = q.nanos;
                } catch (InterruptedException ie) {
                    //如果线程被中断了，就更新Signaller的interrupted成员变量为true
                    interrupted = true;
                }
            }
        }
        //程序执行到这里意味着跳出了上面的循环，可能是任务执行完毕了，也可能是线程被中断了，也可能是等待超时了
        if (q != null) {
            //总之不需要再让当前线程等待了，所以把Signaller对象的thread成员变量设置为null，不需要再让Signaller管理当前线程了
            q.thread = null;
            //判断一下任务是否执行完毕，如果还是没有执行完毕，这就意味着线程被中断了，或者等待超时了
            if (r == null)
                //那就直接从下游任务栈中移除Signaller对象即可，线程已经不等待了，也不需要在任务执行完毕后唤醒当前线程了
                cleanStack();
        }
        //如果任务执行完毕，已经有了结果
        if (r != null) {
            //然后判断出线程被中断过
            if (interrupted)
                //那就恢复线程被中断的标志
                Thread.currentThread().interrupt();
            //处理下游任务栈的任务，唤醒下游任务
            postComplete();
            //返回任务结果
            return r;
        }
        //如果任务没有执行完毕，并且线程被中断过
        else if (interrupted)
            //那就直接返回null即可，返回null之后，在外层方法中会把这个结果交给reportGet()方法处理
            //在reportGet()方法中，如果发现结果为null，就会抛出InterruptedException异常
            return null;
        else
            //执行到这里意味着线程没有被中断，任务也没有结果，那肯定就是超时了才结束上面循环的
            //所以返回等待超时异常即可
            throw new TimeoutException();
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：同步执行Function任务，并返回新的结果
     */
    @Override
    public <U> CompletableFuture<U> thenApply(Function<? super T, ? extends U> action) {
        //这里传进去的第一个参数为null，意味着不指定执行action函数的执行器，那么就会在当前线程中执行
        //这也就是当前方法是同步执行action函数的原因，如果想异步执行，在源码中还有一个thenApplyAsync()方法，这就是异步执行的方法
        return uniApplyStage(null, action);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：该方法注册的任务会在其依赖的任务执行完毕后执行
     */
    @Override
    public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(null, action);
    }

    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：该方法注册的任务会处理异常结果
     */
    @Override
    public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> action) {
        return uniExceptionallyStage(action);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：创建一个新的CompletableFuture对象的方法，相对于调用该方法的CompletableFuture对象，新创建的CompletableFuture对象的任务会在当前CompletableFuture对象的任务执行完毕后执行
     * 我们可以把新创建的这个CompletableFuture对象成为当前调用该方法的CompletableFuture对象的下游任务，也可以成为下一个阶段的任务
     */
    private <V> CompletableFuture<V> uniApplyStage(Executor e, Function<? super T,? extends V> f) {
        //判断用户定义的Function函数是否为null，如果为null，直接抛出空指针异常
        if (f == null) throw new NullPointerException();
        //声明一个变量，用来存储当前CompletableFuture对象的执行结果
        Object r;
        //判断当前CompletableFuture对象的执行结果是否为null，如果为null，表示任务还没有执行完毕
        if ((r = result) != null)
            //如果不为null，表示任务已经执行完毕了，那么就直接执行用户定义的Function函数即可
            return uniApplyNow(r, e, f);
        //如果当前CompletableFuture对象任务还没有执行完毕
        //那就创建一个新的CompletableFuture对象
        CompletableFuture<V> d = newIncompleteFuture();
        //然后用当前CompletableFuture对象和新创建的CompletableFuture对象创建一个
        //UniCompletion对象，再把这个UniCompletion对象添加到当前CompletableFuture对象的任务栈中
        //这样一来，新创建的UniCompletion对象就是当前CompletableFuture对象的下游任务了
        //只要当前任务执行完毕，就会执行这个下游任务
        unipush(new CompletableFuture.UniApply<T,V>(e, d, this, f));
        //返回新创建的CompletableFuture对象
        return d;
    }



    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：直接执行用户定义的Function函数的方法
     */
    private <V> CompletableFuture<V> uniApplyNow(Object r, Executor e, Function<? super T,? extends V> f) {
        //声明一个变量，用来存储异常
        Throwable x;
        //创建一个新的CompletableFuture对象
        CompletableFuture<V> d = newIncompleteFuture();
        //判断当前CompletableFuture对象的执行结果是否为AltResult
        //如果任务执行结果为异常或者为null，都可以使用AltResult对象来包装
        if (r instanceof AltResult) {
            //判断结果中的异常是否不为null
            if ((x = ((AltResult)r).ex) != null) {
                //不为null则意味着任务执行结果就是异常
                //在这里用异常给新创建的CompletableFuture对象的执行结果赋值即可
                d.result = encodeThrowable(x, r);
                return d;
            }
            //如果当前CompletableFuture对象的执行结果为null，那么就直接返回null即可
            r = null;
        }
        try {
            //程序执行到这里意味着当前CompletableFuture对象的执行结果不是异常，也不是null
            //而是一个正常的结果，那接下来就可以执行用户定义的Function函数了
            if (e != null) {
                //把用户定义的函数包装到Completion对象中，然后把该对象交给执行执行器执行即可
                //new CompletableFuture.UniApply得到的就是一个Completion对象
                //Completion实现了Runnable接口，所以可以交给执行器执行
                e.execute(new CompletableFuture.UniApply<T,V>(null, d, this, f));
            } else {
                //执行到这里意味着并没有指定执行器，那么就在当前线程中执行用户定义的Function函数即可
                @SuppressWarnings("unchecked") T t = (T) r;
                //在这里执行函数，然后把结果赋值给新创建的CompletableFuture对象的执行结果
                d.result = d.encodeValue(f.apply(t));
            }
        } catch (Throwable ex) {
            //执行过程中出现异常则把异常赋值给新创建的CompletableFuture对象的执行结果
            d.result = encodeThrowable(ex);
        }
        //返回新创建的CompletableFuture对象
        return d;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：把指定的Completion对象压入到当前CompletableFuture对象的任务栈中
     * 既然是栈结构，那肯定就是先进后出，后进先出，越是后面压入的任务，越是先执行
     */
    final void unipush(Completion c) {
        //对传入的Completion对象进行非空判断
        if (c != null) {
            //尝试将Completion对象压入到当前CompletableFuture对象的任务栈中
            //注意，这里的当前CompletableFuture对象就是调用unipush()方法的CompletableFuture对象
            while (!tryPushStack(c)) {
                //如果在压入栈的过程中发现当前CompletableFuture对象已经执行完毕了，那就直接执行这个Completion对象包装的任务
                if (result != null) {
                    //因为是压入栈，越是后面压入的Completion对象，越要放在栈顶，也就是链表的头节点
                    //然后把这个Completion对象的next成员变量指向之前的链表头节点，这样一来链表就连接起来了
                    //这里执行的操作会把当前压入的Completion对象的next指针设置为null
                    //也就是说，不管当前要压入栈的Completion对象是否压入成功，现在当前CompletableFuture对象的任务已经执行完毕了
                    //这个要被压入的任务可以直接被执行了，它就不需要成为链表的头节点了，所以断开和链表的连接，方便下面直接执行
                    NEXT.set(c, null);
                    //跳出循环
                    break;
                }
            }
            //再次判断当前CompletableFuture对象的任务是否执行完毕了
            if (result != null)
                //如果任务执行完毕了，直接执行这个Completion对象包装的任务
                //注意，这里方法参数为SYNC，意思为同步执行这个Completion对象包装的任务
                //也就是调用当前方法的线程执行这个任务
                c.tryFire(SYNC);
        }
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：该方法的逻辑和uniApplyStage()方法差不多，所以我就不添加详细注释了，如果调用了一个CompletableFuture对象的whenComplete()方法，就会把用户定义的函数包装成一个UniWhenComplete对象
     * 然后把这个对象压入到当前CompletableFuture对象的任务栈中，这样一来，新创建的UniWhenComplete对象就是当前CompletableFuture对象的下游任务了。当然，如果当前CompletableFuture对象的任务已经执行完毕了，那么就直接执行这个下游任务即可
     */
    private CompletableFuture<T> uniWhenCompleteStage(Executor e, BiConsumer<? super T, ? super Throwable> f) {
        if (f == null) throw new NullPointerException();
        CompletableFuture<T> d = newIncompleteFuture();
        Object r;
        if ((r = result) == null)
            unipush(new CompletableFuture.UniWhenComplete<T>(e, d, this, f));
        else if (e == null)
            //如果没有指定执行器，那就同步执行用户定义的BiConsumer函数
            d.uniWhenComplete(r, f, null);
        else {
            try {
                //如果指定了执行器，那就异步执行用户定义的BiConsumer函数
                e.execute(new CompletableFuture.UniWhenComplete<T>(null, d, this, f));
            } catch (Throwable ex) {
                d.result = encodeThrowable(ex);
            }
        }
        return d;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：直接执行用户定义的BiConsumer函数的方法
     */
    final boolean uniWhenComplete(Object r, BiConsumer<? super T,? super Throwable> f, UniWhenComplete<T> c) {
        T t;
        Throwable x = null;
        //如果当前CompletableFuture对象的任务还没有执行完毕
        if (result == null) {
            try {
                //如果包装着用户定义的BiConsumer函数的UniWhenComplete提供了异步执行任务的方法，也就是claim()方法
                //那么就尝试先异步执行任务，如果异步执行任务失败，那就返回false
                if (c != null && !c.claim())
                    return false;
                //判断前一个CompletableFuture对象的执行结果是否为异常或者为null
                if (r instanceof AltResult) {
                    //如果是异常结果，那就把异常赋值给x变量
                    x = ((AltResult)r).ex;
                    t = null;
                } else {
                    //如果不是异常结果，那就把正常结果赋值给t变量
                    x = null;
                    //将结果类型转换一下
                    @SuppressWarnings("unchecked") T tr = (T) r;
                    t = tr;
                }
                //在这里执行了用户定义的BiConsumer函数，注意，这个BiConsumer函数并没有返回值
                f.accept(t, x);
                if (x == null) {
                    //如果执行过程中没有异常，那就把上一个CompletableFuture对象的执行结果赋值给当前CompletableFuture对象的执行结果
                    internalComplete(r);
                    return true;
                }
            } catch (Throwable ex) {
                //如果执行过程中出现异常，那就把异常赋值给当前CompletableFuture对象的执行结果
                if (x == null)
                    x = ex;
                else if (x != ex)
                    //如果已经有存在异常，并且旧异常且不同于新异常,将新异常添加为被抑制的异常
                    x.addSuppressed(ex);
            }
            //执行到这里就意味着肯定有异常，如果没有异常，在上面603行代码出就退出当前方法了
            //如果有异常那就使用异常结果完成当前CompletableFuture对象
            completeThrowable(x, r);
        }
        return true;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：使用指定的函数处理异常结果的方法，这个方法的逻辑和之前的uniApplyStage、uniWhenCompleteStage类似，所以我就不再重复添加注释了
     */
    private CompletableFuture<T> uniExceptionallyStage(Function<Throwable, ? extends T> action) {
        if(action == null) {
            throw new NullPointerException();
        }
        CompletableFuture<T> downFuture = newIncompleteFuture();
        if(result != null) {
            downFuture.uniExceptionally(result, action, null);
        } else {
            UniExceptionally<T> downTask = new UniExceptionally<>(downFuture, this, action);
            unipush(downTask);
        }

        return downFuture;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：使用用户定义的Function函数处理异常结果的方法
     */
    final boolean uniExceptionally(Object r, Function<? super Throwable, ? extends T> f, UniExceptionally<T> c) {
        Throwable x;
        if (result == null) {
            try {
                if (c != null && !c.claim())
                    return false;
                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
                    completeValue(f.apply(x));
                else//结果不是异常则直接设置完成状态
                    internalComplete(r);
            } catch (Throwable ex) {
                completeThrowable(ex);
            }
        }
        return true;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：完成当前CompletableFuture对象任务的方法，并且这个方法一旦被调用，就会触发当前CompletableFuture对象的下游任务执行
     */
    public boolean complete(T result) {
        //设置当前CompletableFuture阶段的执行结果为指定的返回值
        boolean triggered = completeValue(result);
        //递归处理当前阶段的下游任务栈(会触发tryFire(NESTED))
        //这个postComplete()方法，是CompletableFuture类中最核心的方法
        postComplete();
        return triggered;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：使用异常完成当前CompletableFuture对象任务的方法，并且这个方法一旦被调用，就会触发当前CompletableFuture对象的下游任务执行
     */
    public boolean completeExceptionally(Throwable ex) {
        if(ex == null) {
            throw new NullPointerException();
        }
        AltResult result = new AltResult(ex);
        boolean triggered = internalComplete(result);
        postComplete();
        return triggered;
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：设置任务结果为null的方法
     */
    final boolean completeNull() {
        return RESULT.compareAndSet(this, null, NIL);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：使用非异常结果完成CompletableFuture对象任务的方法
     */
    final boolean completeValue(T t) {
        return RESULT.compareAndSet(this, null, (t == null) ? NIL : t);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：使用异常结果完成CompletableFuture对象任务的方法
     */
    final boolean completeThrowable(Throwable ex) {
        return RESULT.compareAndSet(this, null, encodeThrowable(ex));
    }


    /**
     * Completes with the given (non-null) exceptional result as a
     * wrapped CompletionException unless it is one already, unless
     * already completed.  May complete with the given Object r
     * (which must have been the result of a source future) if it is
     * equivalent, i.e. if this is a simple propagation of an
     * existing CompletionException.
     */
    final boolean completeThrowable(Throwable ex, Object result) {
        return RESULT.compareAndSet(this, null, encodeThrowable(ex, result));
    }


    /**
     * Completes with r or a copy of r, unless already completed.
     * If exceptional, r is first coerced to a CompletionException.
     */
    final boolean completeRelay(Object result) {
        return RESULT.compareAndSet(this, null, encodeRelay(result));
    }


    /** Returns the encoding of the given non-exceptional value. */
    final Object encodeValue(T result) {
        return (result == null) ? NIL : result;
    }

    /**
     * Returns the encoding of the given (non-null) exception as a wrapped CompletionException unless it is one already.
     */
    static AltResult encodeThrowable(Throwable ex) {
        Throwable throwable = (ex instanceof CompletionException) ? ex : new CompletionException(ex);
        return new AltResult(throwable);
    }

    /**
     * Returns the encoding of the given (non-null) exception as a
     * wrapped CompletionException unless it is one already.  May
     * return the given Object r (which must have been the result of a
     * source future) if it is equivalent, i.e. if this is a simple
     * relay of an existing CompletionException.
     */
    static Object encodeThrowable(Throwable ex, Object result) {
        if(!(ex instanceof CompletionException)) {
            ex = new CompletionException(ex);
            return new AltResult(ex);
        }
        if(result instanceof AltResult && ex == ((AltResult) result).ex) {
            return result;
        }
        return new AltResult(ex);
    }

    /**
     * Returns the encoding of a copied outcome; if exceptional,
     * rewraps as a CompletionException, else returns argument.
     */
    static Object encodeRelay(Object result) {
        Throwable ex;
        if(result instanceof AltResult && (ex = ((AltResult) result).ex) != null && !(ex instanceof CompletionException)) {
            result = new AltResult(new CompletionException(ex));
        }
        return result;
    }

    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：尝试把指定的Completion对象压入到当前CompletableFuture对象的任务栈中
     */
    final boolean tryPushStack(Completion task) {
        //得到当前CompletableFuture对象的任务栈的栈顶
        //这个栈顶一开始为null
        Completion top = stack;
        //把指定的Completion对象的next成员变量指向当前CompletableFuture对象的任务栈的栈顶
        NEXT.set(task, top);
        //然后把当前CompletableFuture对象的任务栈的栈顶指向指定的Completion对象
        //这样一来，指定的Completion对象就成为了当前CompletableFuture对象的任务栈的栈顶，也就是说新压入的Completion对象
        //就是新的栈顶，符合栈结构先进后出，后进先出的特点
        return STACK.compareAndSet(this, top, task);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：把指定的Completion对象压入到当前CompletableFuture对象的任务栈中，直到操作成功才退出该方法
     */
    final void pushStack(Completion task) {
        do {
        } while(!tryPushStack(task));
    }



    final void cleanStack() {
        Completion p = stack;
        for (boolean unlinked = false;;) {
            if (p == null)
                return;
            else if (p.isLive()) {
                if (unlinked)
                    return;
                else
                    break;
            }
            else if (STACK.weakCompareAndSet(this, p, (p = p.next)))
                unlinked = true;
            else
                p = stack;
        }
        for (Completion q = p.next; q != null;) {
            Completion s = q.next;
            if (q.isLive()) {
                p = q;
                q = s;
            }
            else if (NEXT.weakCompareAndSet(p, q, s))
                break;
            else
                q = p.next;
        }
    }
    
    
    
    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @date:2025/3/25
     * @方法描述：处理当前CompletableFuture对象的任务栈中所有任务的方法
     */
    final void postComplete() {
        CompletableFuture<?> future = this;
        while(true) {
            Completion head = future.stack;
            if(head == null) {
                //这里的这个分支目前还不会进入
                //因为我也想不到会有什么情况，会让head.tryFire(NESTED)返回一个不是null的值
                //并且其stack还不为空，因为head.tryFire(NESTED)执行的时候会判断，如果返回了一个CompletableFuture对象
                //那么这个CompletableFuture对象的stack就一定不是null，因为只有注册了回调方法的CompletableFuture对象才会被返回
                //如果没有注册回调方法，那么head.tryFire(NESTED)返回的就是null，而只要返回null，那么future就会被this赋值
                //也就会等于this了，也就不会进入这个分支了，大家可以思考思考有什么情况会让程序进入下面这个分支，如果有的话可以告诉我
                if(future != this) {
                    future = this;
                    head = future.stack;
                    if(head == null) {
                        return;
                    }
                } else {
                    return;
                }
            }
            Completion next = head.next;
            if(STACK.compareAndSet(future, head, next)) {
                if(next != null) {
                    if(future != this) {
                        pushStack(head);
                        continue;
                    }
                    NEXT.compareAndSet(head, next, null);
                }
                CompletableFuture<?> downFuture = head.tryFire(NESTED);
                future = (downFuture == null) ? this : downFuture;
            }
        }
    }



    final CompletableFuture<T> postFire(CompletableFuture<?> upFuture, int mode) {
        if(upFuture != null && upFuture.stack != null) {
            Object upResult = upFuture.result;
            if(upResult == null) {
                upFuture.cleanStack();
            }
            if(mode >= 0 && (upResult != null || upFuture.result != null)) {
                upFuture.postComplete();
            }
        }
        if(result != null && stack != null) {
            if(mode<0) {
                return this;
            }
            postComplete();
        }

        return null;
    }



    //包装异常结果或者结果为null的内部类
    static final class AltResult {

        final Throwable ex;

        AltResult(Throwable ex) {
            this.ex = ex;
        }
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：whenComplete()方法定义的函数都会被包装到UniWhenComplete对象中，UniWhenComplete是UniCompletion的子类。
     * 然后该对象会被压入到当前CompletableFuture对象的任务栈中
     */
    @SuppressWarnings("serial")
    abstract static class UniCompletion<T, V> extends Completion {
        //执行用户定义的函数的执行器
        Executor executor;
        //当前阶段，待填充任务执行结果，所谓当前阶段就是创建当前UniWhenComplete对象时，一起创建的新的CompletableFuture对象
        CompletableFuture<V> future;
        //当前阶段的上游阶段，即当前阶段的依赖项
        //哪个CompletableFuture对象调用了thenApply()、whenComplete()方法，那么这个CompletableFuture对象就是上游阶段
        //而在thenApply()、whenComplete()方法中创建的新的CompletableFuture对象就是当前阶段，也可以称为
        //调用了thenApply()、whenComplete()方法的CompletableFuture对象的下游阶段
        CompletableFuture<T> upFuture1;

        UniCompletion(Executor executor, CompletableFuture<V> future, CompletableFuture<T> upFuture1) {
            this.executor = executor;
            this.future = future;
            this.upFuture1 = upFuture1;
        }


        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：异步执行用户定义的函数的方法，如果异步执行失败，则返回false，大家可以先不必深究这个方法，等后面我为大家讲解CompletableFuture异步执行任务的内容时，再来深究这个方法
         */
        final boolean claim() {
            Executor executor = this.executor;
            if(compareAndSetForkJoinTaskTag((short) 0, (short) 1)) {
                if(executor == null) {
                    return true;
                }
                this.executor = null;
                executor.execute(this);
            }
            return false;
        }


        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：判断当前UniCompletion对象是否是活跃的。其实是这样，当UniCompletion对象被加入到一个CompletableFuture对象的任务栈中时，这个时候它就是活跃的
         * 当CompletableFuture对象任务执行完毕，并且触发下游任务执行，下游任务也执行完毕了，这个时候UniCompletion对象就是不活跃的了，因为执行完毕的UniCompletion对象
         * 会把future成员变量重置为null，具体逻辑在UniCompletion的子类，也就是UniWhenComplete类tryFire()方法中
         * 所以通过判断future成员变量是否为null，就可以判断UniCompletion对象是否是活跃的
         */
        final boolean isLive() {
            return this.future != null;
        }
    }




    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：刚才我们已经看完了这个内部类的父类，也就是UniCompletion类，现在可以看看子类了，whenComplete()方法定义的函数都会被包装到UniWhenComplete对象中，而UniWhenComplete是UniCompletion的子类。
     * 然后该对象会被压入到当前CompletableFuture对象的任务栈中
     */
    @SuppressWarnings("serial")
    static final class UniWhenComplete<T> extends UniCompletion<T, T> {

        //用户定义的要被执行的函数，这个函数需要接收上游任务的执行结果和异常作为方法参数
        BiConsumer<? super T, ? super Throwable> action;

        UniWhenComplete(Executor executor, CompletableFuture<T> future, CompletableFuture<T> upFuture1, BiConsumer<? super T, ? super Throwable> action) {
            super(executor, future, upFuture1);
            this.action = action;
        }

        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：执行用户定义的action函数的方法，方法参数mode表示执行方式，mode=1表示异步执行，mode=0表示同步执行，mode=-1表示嵌套执行
         */
        final CompletableFuture<T> tryFire(int mode) {
            //这里得到的future成员变量就是当前阶段，也就是创建当前UniWhenComplete对象时，一起创建的新的CompletableFuture对象
            CompletableFuture<T> stage = this.future;
            //这个upFuture1成员变量就是上游阶段，也就是当前阶段的依赖项，也就是调用了whenComplete()方法的CompletableFuture对象
            CompletableFuture<T> upFuture1 = this.upFuture1;
            //对用户定义的函数进行判空处理
            if(action == null || stage == null) {
                return null;
            }
            //判断上游阶段是否存在，或者上游阶段是否已经执行完毕
            //没有执行完毕，直接返回即可
            if(upFuture1 == null || upFuture1.result == null) {
                return null;
            }
            //执行到这里意味着上游阶段执行完毕了，也得到了上游阶段的执行结果，接下来可以执行用户定义的action函数了
            if(!stage.uniWhenComplete(upFuture1.result, action, mode>0 ? null : this)) {
                return null;
            }
            //用户定义的函数执行完毕之后，就意味着当前阶段的任务执行完毕了，接下来就可以释放相关资源，帮助垃圾回收了
            this.future = null;
            this.upFuture1 = null;
            this.action = null;
            //这里的这个操作很重要，会返回一个CompletableFuture对象，返回的这个CompletableFuture对象非常重要
            //这决定了在postComplete()方法中如何递归处理后续的下游阶段的任务
            //关于这一段的逻辑有点复杂，有点绕，所以大家可以直接看对应的文章
            //我在文章中把这一段的逻辑剖析得非常透彻
            return stage.postFire(upFuture1, mode);
        }
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：thenApply()方法定义的函数都会被包装到UniApply对象中，然后该对象会被压入到当前CompletableFuture对象的任务栈中
     */
    @SuppressWarnings("serial")
    static final class UniApply<T, V> extends UniCompletion<T, V> {

        //用户定义的要被执行的函数，这个函数需要接收上游任务的执行结果作为方法参数
        Function<? super T, ? extends V> action;

        UniApply(Executor executor, CompletableFuture<V> future, CompletableFuture<T> upFuture1, Function<? super T, ? extends V> action) {
            super(executor, future, upFuture1);
            this.action = action;
        }

        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：执行用户定义的action函数的方法，方法参数mode表示执行方式，mode=1表示异步执行，mode=0表示同步执行，mode=-1表示嵌套执行
         * 如果上游任务得执行结果是异常，那么直接返回异常结果，不再执行用户定义的action函数
         */
        final CompletableFuture<V> tryFire(int mode) {

            //这里得到的future成员变量就是当前阶段，也就是创建当前UniWhenComplete对象时，一起创建的新的CompletableFuture对象
            CompletableFuture<V> future = this.future;
            //这个upFuture1成员变量就是上游阶段，也就是当前阶段的依赖项，也就是调用了whenComplete()方法的CompletableFuture对象
            CompletableFuture<T> upFuture1 = this.upFuture1;
            //上游任务执行的结果
            Object upResult1;
            //对用户定义的函数进行判空处理
            if(future == null || this.action == null) {
                return null;
            }
            //如果上游阶段的任务还没有执行完毕，没有结果，直接返回即可
            if(upFuture1 == null || (upResult1 = upFuture1.result) == null) {
                return null;
            }
            //如果当前阶段的任务已经有结果了，说明当前阶段的任务执行完毕了，用户定义的函数已经执行了
            //那就直接设置当前阶段任务为完成即可
            if(future.result != null) {
                return tryComplete(future, upFuture1, mode);
            }
            //如果上游阶段的任务执行结果是异常，那么直接返回异常结果，不再执行用户定义的action函数
            if(upResult1 instanceof AltResult) {
                Throwable ex = ((AltResult) upResult1).ex;
                if(ex != null) {
                    //把异常设置为当前阶段的任务执行结果
                    future.completeThrowable(ex, upResult1);
                    //设置当前阶段任务为完成即可
                    return tryComplete(future, upFuture1, mode);
                }
                //程序执行到这里意味着上游阶段的任务执行结果不是异常，那就是null
                upResult1 = null;
            }
            //程序执行到这里，就意味着上游阶段的任务执行结果不是异常，可能是正常结果，也可能是null
            try {
                //判断执行用户定义的函数的方式，看看是不是同步执行或嵌套执行
                //如果是的话，说明当前要执行的任务是由执行上游任务的线程同步执行的
                if(mode<=0) {
                    //这里做了一个操作，那就是异步执行用户定义的函数
                    if(!claim()) {
                        //但我们这里肯定无法异步执行，因为我们没有定义异步执行的执行器，所以claim()方法会返回true
                        //程序也就不会进入到当前分支中了
                        return null;
                    }
                }
                //这里就是真正执行用户定义的函数的操作
                //得到执行结果
                @SuppressWarnings("unchecked")
                V result = this.action.apply((T) upResult1);
                //为当前任务阶段设置执行结果
                future.completeValue(result);
            } catch(Throwable ex) {
                //如果执行过程中出现异常，则设置异常结果
                future.completeThrowable(ex);
            }
            //为当前任务阶段设置完成状态
            return tryComplete(future, upFuture1, mode);
        }


        private CompletableFuture<V> tryComplete(CompletableFuture<V> future, CompletableFuture<T> upFuture1, int mode) {
            this.future = null;
            this.upFuture1 = null;
            this.action = null;
            //检查上游和下游任务栈任务处理情况
            return future.postFire(upFuture1, mode);
        }
    }




    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：看完了上面两个内部类后，这个内部类中的内容对大家来说肯定就很简单了，所以我就不添加详细注释了，大家自己看看就行
     */
    @SuppressWarnings("serial")
    static final class UniExceptionally<T> extends UniCompletion<T, T> {
        Function<? super Throwable, ? extends T> action;

        UniExceptionally(CompletableFuture<T> future, CompletableFuture<T> upFuture1, Function<? super Throwable, ? extends T> action) {
            super(null, future, upFuture1);
            this.action = action;
        }

        final CompletableFuture<T> tryFire(int mode) {

            CompletableFuture<T> future = this.future;
            CompletableFuture<T> upFuture1 = this.upFuture1;
            Object upResult1;

            if(action == null || future == null) {
                return null;
            }

            if(upFuture1 == null || (upResult1 = upFuture1.result) == null) {
                return null;
            }

            if(!future.uniExceptionally(upResult1, action, this)) {
                return null;
            }

            this.future = null;
            this.upFuture1 = null;
            this.action = null;

            return future.postFire(upFuture1, mode);
        }
    }



    //异步任务接口
    public interface AsynchronousCompletionTask {
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：该类的对象表示一个任务，该任务会在CompletableFuture对象的任务栈中执行，也可以被执行器异步执行
     */
    @SuppressWarnings("serial")
    abstract static class Completion extends ForkJoinTask<Void> implements Runnable, AsynchronousCompletionTask {
        //指向下一个Completion任务的指针
        volatile Completion next;

        //异步执行当前任务
        public final boolean exec() {
            tryFire(ASYNC);
            return false;
        }

        //异步执行当前任务
        public final void run() {
            tryFire(ASYNC);
        }

        public final Void getRawResult() {
            return null;
        }

        public final void setRawResult(Void v) {
        }


        //执行当前任务
        abstract CompletableFuture<?> tryFire(int mode);

        //判断当前任务是否活跃
        abstract boolean isLive();
    }



    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @方法描述：该内部类的对象就是用来管理线程阻塞与环形的
     */
    @SuppressWarnings("serial")
    static final class Signaller extends Completion implements ForkJoinPool.ManagedBlocker {
        //线程需要阻塞的时间
        long nanos;
        //线程阻塞的超时截止时间
        final long deadline;
        //线程是否可以响应中断
        final boolean interruptible;
        //线程是否被中断
        boolean interrupted;
        //被管理的线程
        volatile Thread thread;


        Signaller(boolean interruptible, long nanos, long deadline) {
            this.thread = Thread.currentThread();
            this.interruptible = interruptible;
            this.nanos = nanos;
            this.deadline = deadline;
        }


        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：唤醒阻塞线程的方法
         */
        final CompletableFuture<?> tryFire(int ignore) {
            Thread w;
            if ((w = thread) != null) {
                thread = null;
                LockSupport.unpark(w);
                System.out.println("主线程被唤醒了！");
            }
            return null;
        }


        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：判断被管理的线程是否可以被释放的方法，其实就是唤醒线程的方法
         */
        public boolean isReleasable() {
            //首先检查线程是否被中断了
            if (Thread.interrupted())
                //如果被中断了则更新线程中断标志
                interrupted = true;
            //如果当前线程需要响应中断标志，或者线程阻塞已到超时时间
            //或者线程已经被唤醒了，也就是tryFire()方法被调用了，这个时候就可以释放线程了
            return ((interrupted && interruptible) ||
                    (deadline != 0L &&
                            (nanos <= 0L ||
                                    (nanos = deadline - System.nanoTime()) <= 0L)) ||
                    thread == null);
        }


        /**
         * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
         * @author：陈清风扬，个人微信号：chenqingfengyangjj。
         * @方法描述：阻塞线程的方法，直到线程可以被唤醒
         */
        public boolean block() {
            //循环判断当前管理的线程是否可以被唤醒
            while (!isReleasable()) {
                //如果没有设置超时时间
                if (deadline == 0L)
                    //那么当前线程就需要一直阻塞，直到CompletableFuture任务执行完毕
                    LockSupport.park(this);
                else
                    //如果设置了超时时间，那么线程只需阻塞到超时时间即可
                    LockSupport.parkNanos(this, nanos);
            }
            return true;
        }


        final boolean isLive() { return thread != null; }
    }
}
